home *** CD-ROM | disk | FTP | other *** search
- 1 DEVICES
-
- 1.1 INTRODUCTION
-
- The Amiga's operating system must be able to handle input events
- from the keyboard or gameports, monitoring the disk drivers,
- sending data to the parallel device and communicating with the
- serial port, playing stereo sound with its audio chips, etc...
- If this was not enough, all these things have to be monitored
- in a multitasking environment where several tasks (programs) may
- run simultaneously.
-
- As you understand this is a very complicated system that
- controls all these things. Despite the complexity it must also
- be very fast so as little processing time as possible is used.
-
- The part of the Amiga which takes care of all these routines
- is usually referred as "Exec". Exec handles tasks and task-
- switching, interrupts, messages and controls all Amiga's
- "devices".
-
- In this chapter we will look at how you can, with help of Exec,
- control the devices. A device is a collection of special
- routines which handles things like disk drivers, serial and
- parallel ports, input events, sound generating etc... Although
- all these routines are very different they are all handled in
- almost the same manner. This means that once you know how to
- control one of the devices, you do not need to read much more
- before you can control all of them.
-
-
-
- 1.2 REQUESTS
-
- When you want to do something with a device you fill a "request
- block" with your requirements and send it to Exec. Exec will
- now take care of everything. Once it has, successfully or not,
- completed your request it sends a message to you which tells
- you that your request has been completed.
-
-
-
- 1.2.1 IOREQUEST
-
- The "request block" is actually an IORequest structure defined
- in header file "exec/io.h". It looks like this:
-
- struct IORequest
- {
- struct Message io_Message;
- struct Device *io_Device;
- struct Unit *io_Unit;
- UWORD io_Command;
- UBYTE io_Flags;
- BYTE io_Error;
- };
-
- io_Message: The top part of the request block consists of a
- Message structure. It is used by Exec when the
- request is sent around inside the Amiga. It is
- also used to queue requests at a device's port.
- You do not need to bother very much about this
- part since Exec takes care of most things. You
- must however initialize it correctly before you
- may start to use the request.
-
- io_Device: Pointer to the device which this request has been
- prepared for. Se below for more information about
- how to initialize a request block.
-
- io_Unit: Some devices, the trackdisk device for example,
- consists of several units (df0:, df1, and so on),
- and this part is used to identify which unit should
- be affected.
-
- io_Command: It is here you set your command. There exist both
- standard commands which are handle by most
- devices, but there exist also a lot of special
- unique commands for some devices. See below for
- more information about available commands.
-
- io_Flags: This field is used to set special flags.
-
- io_Error: When the request has been completed you can look
- at this field to see if your request was
- successfully or not completed.
-
-
-
- 1.2.2 IOSTDREQ
-
- The IORequest structure is the shortest request block you may
- use, and consists of only the most important fields. Normally
- you need to use a request block which is a bit larger. Since
- it is the most commonly used request block, it is called
- the "standard request block" (IOStdReq) and is defined like
- this: (Also declared in the header file "exec/io.h")
-
- struct IOStdReq
- {
- struct Message io_Message;
- struct Device *io_Device;
- struct Unit *io_Unit;
- UWORD io_Command;
- UBYTE io_Flags;
- BYTE io_Error;
-
- ULONG io_Actual;
- ULONG io_Length;
- APTR io_Data;
- ULONG io_Offset;
- };
-
- As you can see the top part is identical to the IORequest
- structure, but there have been four extra fields added.
-
- io_Actual: When your request has been complete you can look
- here to find the actual number of bytes transferred.
- If this value is not the same as the number of
- bytes you wanted to transfer you know something
- went wrong.
-
- io_Length: The number of bytes you want to transfer. If you
- want to continue to send/retrieve information until
- some special external event, set this field to -1.
-
- io_Data: If you are going to send (write) data, this should
- be a pointer to the data that should be sent. If you
- want to retrieve (read) data this should be a
- pointer to a memory buffer were all data which is
- collected should be store.
-
- io_Offset: Special offset value used by some devices.
-
-
- To make life simpler there exist a special function which will
- automatically allocate and preinitialize the request block. The
- function is called CreateStdIO(). However, before you may use
- this function you have to create a message port to which the
- device can communicate with you. Simply use the CreatePort()
- function which is described in the "System" manual, chapter
- "Messages".
-
- CreatePort() allocates and initializes a MsgPort structure.
- Normally the message port should only be used by you and the
- device, so you do not need to give it any name. The priority
- should usually be set to 0 (normal priority).
-
-
- Synopsis: msg_port = CreatePort( name, pri );
-
- msg_port: (struct MsgPort *) Pointer to the new MsgPort
- structure, or NULL if something went wrong.
-
- name: (char *) Pointer to a string containing the name
- of the message port, or NULL. When working with
- devices you normally do not need to use any name.
-
- msgp: (struct MsgPort *) Pointer to the MsgPort structure
- that should be allocated.
-
- pri: (BYTE) This message port's priority. Usually set
- to 0 (normal priority).
-
-
- Once you have successfully created the reply port you can
- allocate and initialize the standard request block with help
- of the CreateStdIO() function. Give it a pointer to the
- reply port as the only parameter.
-
- Synopsis: std_req = CreateStdIO( msg_port );
-
- std_req: (struct IORequest *) Pointer to the new standard
- request block (struct IOStdReq *), or NULL if the
- request block could not be created.
-
- msg_port: (struct MsgPort *) Pointer to the message port
- the device should use to communicate with you.
-
-
- When your program terminates you must delete all request
- blocks you have created. Use the DeleteStdIO() function.
-
- Synopsis: DeleteStdIO( std_req );
-
- std_req: (struct IOStdReq *) Pointer to the standard
- request block you want to delete.
-
-
- All message ports must also be deleted, but remember to first
- deallocate the standard request block to which the message
- port is connected to, before you delete the message port itself.
-
- Synopsis: DeletePort( msg_port );
-
- msg_port: (struct MsgPort *) Pointer to the MsgPort structure
- that should be deallocated.
-
-
- Here is a short example:
-
- /* Pointer to the standard request block: */
- struct IOStdReq *std_req;
-
- /* Pointer to the message (reply) port: */
- struct MsgPort *msg_port;
-
-
- /* 1. Create a message port so the device can */
- /* communicate with us: (No name, normal priority) */
- msg_port = CreatePort( NULL, 0 );
- if( !msg_port )
- clean_up( "ERROR! Could not create message port!" );
-
- /* 2. Allocate and initialize a new standard request block. */
- /* It should use our new message port as reply port: */
- std_req = CreateStdIO( msg_port );
- if( !std_req )
- clean_up( "ERROR! Could not allocate the request block!" );
-
- ...
-
-
- /* Deallocate standard request block: */
- DeleteStdIO( std_req );
-
- /* Close message port: */
- DeletePort( msg_port );
-
-
-
- 1.2.3 IOEXTREQ
-
- As if the extra IOStdReq structure would not be enough. There
- exist an even larger request block, usually referred as the
- "extended request block". This request structure always looks
- different depending on which device it is used for. It always
- consists of a IORequest structure, or at least the same fields,
- at the top, but the rest may vary. See the following chapters
- for more information about this request block.
-
- Since the size of this extended request block varies you can
- not use the CreateStdIO() function to create and initialize it.
- Instead you have to use the CreateExtIO() function which will
- allocate a request block of any specified size. Except of
- allocating a larger request block it will do exactly the same
- things as CreateStdIO(). (Remember that you first have to
- create a message (reply) port as described above.)
-
- Synopsis: ext_req = CreateExtIO( msg_port, size );
-
- ext_req: (struct IORequest *) Pointer to the new extended
- request block, or NULL if the request block could
- not be created.
-
- msg_port: (struct MsgPort *) Pointer to the message port
- the device should use to communicate with you.
-
- size: (long) The number of bytes that should be allocated
- for the extended request block. Use the function
- sizeof() to find the exact number of bytes needed.
-
-
- When your program terminates all request block have to be
- deleted. Extended request blocks are deleted with the special
- DeleteExtIO() function. Once the request block has been deleted
- you should also delete the message (reply) port.
-
- Synopsis: DeleteExtIO( std_req, size );
-
- std_req: (struct IOStdReq *) Pointer to the extended
- request block you want to delete.
-
- size: (long) The size of the request block, in bytes.
-
-
- Here is a short example: (In this example we will use an
- extended request block designed for the "serial device".)
-
- /* Pointer to the extended request block: */
- struct IOExtSer *ext_req;
-
- /* Pointer to the message (reply) port: */
- struct MsgPort *msg_port;
-
-
- /* 1. Create a message port so the device can */
- /* communicate with us: (No name, normal priority) */
- msg_port = CreatePort( NULL, 0 );
- if( !msg_port )
- clean_up( "ERROR! Could not create message port!" );
-
- /* 2. Allocate and initialize a new extended request block. */
- /* It should use our new message port as reply port, and */
- /* have the same size as an IOExtSer structure: */
- ext_req = CreateExtIO( msg_port, sizeof( struct IOExtSer ) );
- if( !ext_req )
- clean_up( "ERROR! Could not allocate the request block!" );
-
- ...
-
-
- /* Deallocate extended request block: (Must be the same */
- /* size as when allocated!) */
- DeleteExtIO( ext_req, sizeof( struct IOExtSer ) );
-
- /* Close message port: */
- DeletePort( msg_port );
-
-
-
- 1.3 PREPARE THE DEVICE
-
- Once you have created a request block you may "open" the device
- to which the request block should be connected to. Note that
- some devices only need a standard request block (or just a
- IORequest structure), but others may need larger extended
- request blocks. See the following chapters for more information.
-
- To open a device simply use the OpenDevice() function.
-
- Synopsis: error = OpenDevice( name, unit, req, flags );
-
- error: (long) If OpenDevice() managed to open the device
- it returns 0, else an error number is returned.
-
- name: (char *) Name of the device you want to open.
- See the following chapters for more information.
-
- unit: (long) Which unit you want to open. Some devices
- does not have several units and this field is then
- ignored.
-
- req: (struct IORequest *) Pointer to a request block.
- Note that some devices may need a larger extended
- request blocks.
-
- flags: (long) Special flags may sometimes be used here,
- otherwise this field is ignored.
-
-
- As usual, everything that you open must be closed before the
- program may terminated. To close a device simply call the
- CloseDevice() function. After you have closed the device you
- should delete the request block and then the message port.
- (Unless you want to reopen the device later on.)
-
- Synopsis: CloseDevice( req );
-
- reg: (struct IORequest *) Pointer to the device's
- request block.
-
-
-
- 1.4 STANDARD EXEC COMMANDS
-
- There exist eight standard commands which most devices
- understand. If the device is already occupied by some other
- request, your request is queued on a FIFO basis (First In
- First Out). For some devices it may happen that the other
- requests are aborted and your started if your request has
- higher priority.
-
- The eight "standard" commands are:
-
- CMD_RESET This command will reset the device. All currently
- queued requests are removed (aborted) and the
- device is reinitialized to the default values.
-
- CMD_READ This command tells the device to start reading
- (collecting) data. The "io_Length" field of the
- request block states how many bytes should be
- read, and the "io_Actual" field will contain the
- number of bytes actually transferred.
-
- CMD_WRITE This command tells the device to start writing
- (sending) data. The "io_Length" field of the
- request block states how many bytes should be
- written, and the "io_Actual" field will contain
- the number of bytes actually transferred.
-
- CMD_UPDATE This command will update a device in that sense
- that any values still in the internal buffers are
- written out. Most times this is automatically
- done, but this command may be needed when you
- are working with the "trackdisk device" for
- example.
-
- CMD_CLEAR This command will clear any internal memory
- buffers.
-
- CMD_STOP When this command is sent to a device all
- communication to and from that device will be
- temporarily halted. Use the "CMD_START" command
- to restart the communication.
-
- CMD_START This command tells the device to restart the
- communication which has temporarily been halted
- by a "CMD_STOP" command.
-
- CMD_FLUSH If this command is sent to a device all currently
- queued requests will be removed (aborted).
-
-
- There exist several more commands, but those are device
- depending, and may therefore only be used with a certain
- device. See the following chapters for more information about
- these special device commands.
-
-
-
- 1.5 SEND REQUESTS
-
- Once you have initialized the request block and "opened" the
- desired device, which is described in more details in the
- following chapters, you only have to send the request to Exec
- and the rest will automatically be done for you. (Isn't that
- nice! At last you do not need to worry about everything.)
-
- When you send requests to a device the commands can either be
- synchronous or asynchronous. When you send synchronous commands
- your program is halted until the request has been completed.
- With asynchronous commands your program will continue to run
- while the device is executing your request.
-
-
-
- 1.5.1 SYNCHRONOUS COMMANDS
-
- Synchronous commands are very easy to handle. You simply send
- your request with the DoIO() function. Your program will
- automatically be put to sleep while the device is executing
- your command, and once it has finished your program will
- wake up. Since your program is put to sleep ("task sleep")
- no processing time is waisted while you are waiting for your
- request to be completed.
-
- Synopsis: error = DoIO( req );
-
- error: (long) DoIO() will return first when the request has
- been completed or something has failed. If the
- request was successfully completed zero is returned,
- else an error number is returned. What error number
- depends on which device was used. See below for a
- complete list of standard error commands.
-
- req: (struct IORequest *) Pointer to the request you
- want to have executed.
-
-
-
- 1.5.2 ASYNCHRONOUS COMMANDS
-
- Asynchronous requests are a bit more complicated to handle.
- Since your program will continue to run while your request is
- being executed you do not know when it has been completed.
- Asynchronous requests can be very useful when you do not want
- to pause the program while waiting. (It would not be a very
- nice game if it was halted each time the user did not move the
- joystick for example.)
-
- You start asynchronous requests with help of the SendIO()
- function.
-
- Synopsis: SendIO( req )
-
- req: (struct IORequest *) Pointer to the request you
- want to have executed.
-
-
- After you have issued an asynchronous request there exist
- three different ways to find out when it has been completed.
-
-
-
- 1.5.2.1 KEEP ON CHECKING THE REQUEST UNTIL IT HAS BEEN COMPLETED
-
- You can use the CheckIO() function which will either return
- NULL if the request has not been completed, or it will return
- a pointer to the request if it has been completed.
-
- Synopsis: ptr = CheckIO( req );
-
- ptr: (long) CheckIO() will either return NULL if the
- request have not been completed or it will return a
- pointer to the request block.
-
- req: (struct IORequest *) Pointer to the request you
- want to check.
-
-
- When a request has been completed a message is sent to a
- specified reply port. Note that CheckIO() will not remove the
- message at the reply port. This should be done with the
- Remove() function.
-
- Synopsis: Remove( node );
-
- node: (struct Node *) Pointer to the node that should be
- removed.
-
-
-
- 1.5.2.2 WAIT FOR THE REQUEST TO BE COMPLETED
-
- You can put your program to sleep and wait for the request to
- be completed, by calling the WaitIO() function. WaitIO() will
- automatically remove the message at the reply port.
-
- Synopsis: error = WaitIO( req );
-
- error: (long) WaitIO() will return first when the request,
- that has previously been sent, has been completed or
- something has failed. If the request was successfully
- completed zero is returned, else an error number is
- returned. What error number depends on which device
- was used.
-
- req: (struct IORequest *) Pointer to the request you
- want to wait for to be completed. Note that the
- request must have already been sent to the device
- by either a SendIO() or BeginIO() function call. If
- the request has already been completed WaitIO() will
- immediately return.
-
-
-
- 1.5.2.4 WAIT FOR A REPLY MESSAGE
-
- Since a message is sent to the request block's reply port each
- time the request has been completed you can simply wait for a
- message to arrive. The simplest way is to use the WaitPort()
- function which will put your program to sleep while waiting
- for a message to arrive at the specified port. Note that it
- will not remove the message.
-
- Synopsis: msg = WaitPort( msg_port );
-
- msg: (struct Message *) Pointer to the first message which
- has arrived. Remember that this function will not
- remove the message from the queue. Use the Remove()
- function to do this.
-
- msg_port: (struct MsgPort *) Pointer to the message port which
- you want to monitor. Your program will be put to
- sleep while waiting, and if no message arrive it
- will never wake up, so be careful.
-
-
- Instead of just waiting for one request to be completed you
- can wait fore several ones at the same time. This is extremely
- useful if your program is handling a lot of requests
- simultaneously. Now we need to use the multipurpose Wait()
- function which is described in the "System" manual, chapter
- "Messages".
-
- Synopsis: rsig = Wait( wsig )
-
- rsig: (ULONG) When one of the specified signal bits was
- received, the task is woken up and Wait() returns
- the signal bit value that woke it up.
-
- wsig: (ULONG) The signals we are waiting for. Wait() will
- put the task to sleep, and it will only wake up if
- one of the specified signal bit values is received.
-
-
-
- 1.5.4 QUICK I/O
-
- Although the system with sending requests and messages is very
- fast it may sometimes not be fast enough. If you want to handle
- a lot of data extremely fast you can try to use the "Quick
- mode". When you are using this quick mode Exec tries to skip
- all routines that are not essential. No messages are sent, and
- there is no checking etc...
-
- The quick mode should only be used when really needed, and it
- can not always be used. When you want to try to use the quick
- mode set the IOF_QUICK flag in the "io_Flags" field of the
- request block. To pass the request to Exec you should not use
- the DoIO() or SendIO() functions, but instead the low level
- function BeginIO().
-
- Synopsis: BeginIO( req )
-
- req: (struct IORequest *) Pointer to the request you
- want to have executed. When you want to use the
- quick mode you have to use this low level function
- rather than SendIO() and DoIO().
-
-
- If we were allowed to use the quick mode the request will be
- synchronous. (Your program is put to sleep since all computer
- time is needed to run this fast quick mode.)
-
- If we were not allowed to use the quick mode the request will
- be asynchronous, and is then handled exactly the same as if the
- request had been sent by a SendIO() call.
-
- After you have posted your quick request you must check if you
- were allowed to use this fast mode or not. If not you have to
- wait for the request to be completed and remove the reply
- message yourself. To check if you were allowed quick mode or
- not simply look at the "io_Flags" field of the request block to
- see if the flag IOF_QUICK is still there or not. If the flag is
- still set the request was using the quick mode, and you do not
- need to do anything more. If the flag is not there any more,
- you were not allowed quick mode, and thus you have to wait for
- the asynchronous request to be completed and remove the message
- yourself.
-
-
- /* Initialize the request block as normal. */
- /* The pointer to it is called "ioreq". */
- /* ... */
-
- /* Try to use the "quick" mode: */
- ioreq->IOSer.io_Flags = IOF_QUICK;
-
- /* Do the request: */
- BeginIO( ioreq );
-
- /* Check if the flag IOF_QUICK is still there or not: */
- if( (ioreq->IOSer.io_Flags & IOF_QUICK) )
- {
- /* OK! The request was using quick mode, which means */
- /* that our task was put to sleep while the request was */
- /* executed, and the request has now been completed. */
- /* Since we are using quick mode there are no message */
- /* that should be removed. */
- }
- else
- {
- /* Too bad, we were not allowed to use the quick mode. */
- /* The request should now be treated as if it was */
- /* started with a SendIO() function call. This request */
- /* is asynchronous - request returns immediately. */
-
- /* Wait for the request to be completed. WaitIO() will */
- /* also automatically remove the message at the reply */
- /* port. */
- WaitIO( ioreq );
- }
-
-
-
- 1.5.3 ABORT REQUESTS
-
- You can abort a previously started request by calling the
- AbortIO() function. Of course, only asynchronous commands can
- be aborted, and if the request has already been completed it
- can not be aborted any more.
-
- Synopsis: AbortIO( req )
-
- req: (struct IORequest *) Pointer to the request you
- want to abort.
-
-
-
- 1.6 ERRORS
-
- No one is perfect, and even the devices may sometimes not be
- able to do what you tell them to do (usually because you have
- done something wrong). If something goes fails an error number
- is returned. Each device has it own set of unique error codes
- which are described in the following chapters. There exist,
- however, four error codes that are sent by Exec. (They are all
- defined in the header file "exec/errors.h")
-
- IOERR_OPENFAIL The device (unit) could not be opened. If you
- receive this message there is normally some
- other program currently using the device with
- exclusive mode.
-
- IOERR_ABORTED When you abort a previously started request by
- calling the AbortIO() function, the io_Error
- filed of that request is set to IOERR_ABORTED.
- If you find a request block with this flag set,
- you know that it has been aborted.
-
- IOERR_NOCMD You tried to use a command that is not
- supported by that device.
-
- IOERR_BADLENGTH The length of the request was not valid.
-
-
-
- 1.7 DEVICES
-
- There exist a lot of different devices each specialized to do
- something unique. Some devices are so called "low level
- devices" and are handling a lot of fresh untranslated raw
- data which will be modified and later used by other so called
- "high level devices".
-
- In total there exist 12 devices (14 with the new V2.05 operating
- system) which all will be described in a chapter each. Although
- the devices are so different, they all are handled in much the
- same manner - allocate a message port and a request block, open
- the device and start to send your request, finally close
- everything and quit.
-
- Five devices are not covered in this edition, but will soon be
- added. All registered members will receive more information
- about this as soon as the chapters have been completed.
-
-
-
- 1.7.1 Timer Device
-
- The Timer Device can be used if you want to receive a message
- after a specified time limit. This is one of the so called "low
- level devices", and is used by many other devices. Although the
- timer device does not sound very interesting, it can really be
- useful.
-
-
-
- 1.7.2 Gameport Device
-
- The Gameport Device is a smart little device which reads data
- from the two gameport connectors on the Amiga. The device
- can handle both normal Joystick as well as Mouse movements.
- Even light-pens and other input devices may be connected and
- monitored by this device. These special input devices must
- however have its own drivers which translates the signals to
- for the gameport device understandable form.
-
-
-
- 1.7.3 Audio Device
-
- The Audio Device is used to produce sound. It monitors the four
- hardware sound channels, and can therefore play the sound in
- stereo. Everything from a simple beep to complete songs may be
- played. The audio device can both produce sounds itself or
- directly play sampled (digitized) sound effects.
-
- Sound is an important part of our life and should therefore
- in my opinion also be used a lot in computer programs. Sound
- can be used in most situations, from emergency beeps to
- entertaining melodies.
-
-
-
- 1.7.4 Narrator Device
-
- The Amiga is not only extremely good at producing high quality
- sound. with help of the Narrator Device it can also speak
- almost as a human. Although it is not a Frank Sinatra, it is
- possible to understand what it is saying, and this can be used
- in many situations. Used with care, it is possible to produce
- very good sound.
-
- Sadly, somehow many persons do not like this unique feature of
- the Amiga, and very few programs support the narrator device. I
- believe that artificial speech can be used in many situations,
- and can really be handy for the user. Most "professional"
- programs would really benefit from using the narrator device.
-
-
-
- 1.7.5 Trackdisk Device
-
- With help of the Trackdisk Device you can directly access the
- disk drivers. Data can not only be transferred to and from the
- disks, but you may even format specific sectors of a disk and
- do a lot of other low level stuff.
-
-
-
- 1.7.6 Serial Device
-
- The Serial Device is used to transfer data from and to the
- serial port. It can be used at different speeds (bauds) and
- use seven or eight bit characters. The device also support
- parity (error) checking.
-
-
-
- 1.7.7 Parallel Device
-
- The Parallel device is used to transfer data from and to the
- parallel port. The parallel device is very useful when you
- want very fast communications, and is therefore often used by
- sound samplers and video digitizers. However, the most commonly
- used external device is without question a printer, but you
- should then use the printer device which has specially been
- designed for this purpose.
-
-
-
- 1.7.8 Printer Device
-
- The printer device can use both the serial and parallel device
- depending on to which port the printer is connected to. With
- the printer device you can not only print normal text, special
- printer commands may be sent and you can even print graphics
- with it.
-
- The printer device uses the preferences settings to find out
- to which port the printer is connected, what printer it is,
- and other special settings like margins, paper length etc...
-
-
-
-
- 1.7.9 Keyboard Device
-
- The Keyboard Device is a "low level device" which is used by
- the "Input Device". The keyboard device collects untranslated
- (raw) key codes. This device is very fast and uses very little
- computer time.
-
- This device will be covered in the next version of the manual.
- All registered members will receive more information as soon as
- the next version has been completed.
-
-
-
- 1.7.10 Input Device
-
- The Input Device is a so called "high level device" which
- receives information from the timer, keyboard and gameport
- devices, and puts all this information into one single input
- stream. Very handy and useful device.
-
- This device will be covered in the next version of the manual.
- All registered members will receive more information as soon as
- the next version has been completed.
-
-
-
- 1.7.11 Console Device
-
- The Console Device enables you to handle input and output as
- an intelligent terminal for ASCII characters. Works very close
- with Intuition, and is also a very handy and useful device.
-
- This device will be covered in the next version of the manual.
- All registered members will receive more information as soon as
- the next version has been completed.
-
-
- 1.7.12 Clipboard Device
-
- With the Clipboard Device data can be cut, pasted and copied
- between different programs. Several clips may be used
- simultaneously, and the device supports the IFF standard.
-
- This device will be covered in the next version of the manual.
- All registered members will receive more information as soon as
- the next version has been completed.
-
-
-
- 1.7.13 SCSI AND PCMCIA DEVICE
-
- There exist two new devices. The SCSI device is only available
- with the new V2.0 operating system, and the PCMCIA device exist
- for the moment only on Amiga 600.
-
- These device will be covered in the next version of the manual.
- All registered members will receive more information as soon as
- the next version has been completed.
-
-
-